//package com.goldman.aplt.base.interceptor;
//
//import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
//import com.baomidou.mybatisplus.core.conditions.update.Update;
//import com.baomidou.mybatisplus.core.toolkit.Constants;
//import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
//import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
//import com.goldman.aplt.base.annotation.EncryptedColumn;
//import com.goldman.aplt.base.annotation.EncryptedTable;
//import com.goldman.aplt.base.type.BaseEnumType;
//import com.goldman.aplt.util.EncryUtil;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.springframework.core.annotation.AnnotationUtils;
//
//import java.lang.reflect.Field;
//import java.sql.SQLException;
//import java.util.*;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
///**
// * 字段加密拦截器
// */
//public class DbEncryInterceptor extends JsqlParserSupport implements InnerInterceptor {
//
////    @Resource
////    private EncryUtil encryUtil;
//
//    private static final Pattern PARAM_PAIRS_RE = Pattern.compile("#\\{ew\\.paramNameValuePairs\\.(" + Constants.WRAPPER_PARAM + "\\d+)\\}");
//
//    @Override
//    public void beforeUpdate(Executor executor, MappedStatement mappedStatement, Object parameterObject) throws SQLException {
//        if (Objects.isNull(parameterObject)) {
//            return;
//        }
//        // 通过MybatisPlus自带API（save、insert等）新增数据库时
//        if (!(parameterObject instanceof Map)) {
//            if (needToDecrypt(parameterObject.getClass())) {
//                encryptEntity(parameterObject);
//            }
//            return;
//        }
//        Map paramMap = (Map) parameterObject;
//        Object param;
//        // 通过MybatisPlus自带API（update、updateById等）修改数据库时
//        if (paramMap.containsKey(Constants.ENTITY) && null != (param = paramMap.get(Constants.ENTITY))) {
//            if (needToDecrypt(param.getClass())) {
//                encryptEntity(param);
//            }
//            return;
//        }
//        // 通过在mapper.xml中自定义API修改数据库时
//        if (paramMap.containsKey("entity") && null != (param = paramMap.get("entity"))) {
//            if (needToDecrypt(param.getClass())) {
//                encryptEntity(param);
//            }
//            return;
//        }
//        // 通过UpdateWrapper、LambdaUpdateWrapper修改数据库时
//        if (paramMap.containsKey(Constants.WRAPPER) && null != (param = paramMap.get(Constants.WRAPPER))) {
//            if (param instanceof Update && param instanceof AbstractWrapper) {
//                Class<?> entityClass = mappedStatement.getParameterMap().getType();
//                if (needToDecrypt(entityClass)) {
//                    encryptWrapper(entityClass, param);
//                }
//            }
//            return;
//        }
//    }
//
//    /**
//     * 校验该实例的类是否被@EncryptedTable所注解
//     */
//    private boolean needToDecrypt(Class<?> objectClass) {
//        EncryptedTable sensitiveData = AnnotationUtils.findAnnotation(objectClass, EncryptedTable.class);
//        return Objects.nonNull(sensitiveData);
//    }
//
//    /**
//     * 通过API（save、updateById等）修改数据库时
//     *
//     * @param parameter
//     */
//    private void encryptEntity(Object parameter) {
//        Map<BaseEnumType.E_ENCRY_TYPE, Set<String>> encryRequestMap = new HashMap<>();
//        Map<String, Field> fieldMap = new HashMap<>();
//
//        //取出parameterType的类
//        Class<?> resultClass = parameter.getClass();
//        Field[] declaredFields = resultClass.getDeclaredFields();
//        for (Field field : declaredFields) {
//            //取出所有被EncryptedColumn注解的字段
//            EncryptedColumn sensitiveField = field.getAnnotation(EncryptedColumn.class);
//            if (Objects.isNull(sensitiveField)) {
//                continue;
//            }
//
//            field.setAccessible(true);
//            Object object = null;
//            try {
//                object = field.get(parameter);
//            } catch (IllegalAccessException e) {
//                continue;
//            }
//            //只支持String的解密
//            if (object instanceof String) {
//                String value = (String) object;
//
//                if (encryRequestMap.containsKey(sensitiveField.encryType())) {
//                    Set<String> list = encryRequestMap.get(sensitiveField.encryType());
//                    list.add(value);
//                } else {
//                    Set<String> list = new HashSet<String>();
//                    list.add(value);
//                    encryRequestMap.put(sensitiveField.encryType(), list);
//                }
//                fieldMap.put(value, field);
//            }
//        }
//
//        Set<Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>>> entries = encryRequestMap.entrySet();
//        Iterator<Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>>> it = entries.iterator();
//        while (it.hasNext()) {
//            Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>> entry = it.next();
//            Set<String> keys = entry.getValue();
//
//            Map<String, String> encryResultMap = EncryUtil.encry(keys.stream().toArray(String[]::new), entry.getKey());
//
//            encryResultMap.forEach((k, v) -> {
//                Field field = fieldMap.get(k);
//                try {
//                    field.set(parameter, v);
//                } catch (Exception e) {
//                    throw new RuntimeException(e);
//                }
//            });
//        }
//    }
//
//    /**
//     * 通过UpdateWrapper、LambdaUpdateWrapper修改数据库时
//     *
//     * @param entityClass
//     * @param ewParam
//     */
//    private void encryptWrapper(Class<?> entityClass, Object ewParam) {
//        AbstractWrapper updateWrapper = (AbstractWrapper) ewParam;
//        String sqlSet = updateWrapper.getSqlSet();
//        String[] elArr = sqlSet.split(",");
//        Map<String, String> propMap = new HashMap<>(elArr.length);
//        Arrays.stream(elArr).forEach(el -> {
//            String[] elPart = el.split("=");
//            propMap.put(elPart[0], elPart[1]);
//        });
//
//        Map<BaseEnumType.E_ENCRY_TYPE, Set<String>> encryRequestMap = new HashMap<>();
//        Map<String, String> fieldMap = new HashMap<>();
//
//        //取出parameterType的类
//        Field[] declaredFields = entityClass.getDeclaredFields();
//        for (Field field : declaredFields) {
//            //取出所有被EncryptedColumn注解的字段
//            EncryptedColumn sensitiveField = field.getAnnotation(EncryptedColumn.class);
//            if (Objects.isNull(sensitiveField)) {
//                continue;
//            }
//            String el = propMap.get(field.getName());
//            Matcher matcher = PARAM_PAIRS_RE.matcher(el);
//            if (matcher.matches()) {
//                String valueKey = matcher.group(1);
//                Object object = updateWrapper.getParamNameValuePairs().get(valueKey);
//                if (object instanceof String) {
//                    String value = (String) object;
//
//                    if (encryRequestMap.containsKey(sensitiveField.encryType())) {
//                        Set<String> list = encryRequestMap.get(sensitiveField.encryType());
//                        list.add(value);
//                    } else {
//                        Set<String> list = new HashSet<String>();
//                        list.add(value);
//                        encryRequestMap.put(sensitiveField.encryType(), list);
//                    }
//                    fieldMap.put(value, valueKey);
//                }
//            }
//        }
//
//        Set<Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>>> entries = encryRequestMap.entrySet();
//        Iterator<Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>>> it = entries.iterator();
//        while (it.hasNext()) {
//            Map.Entry<BaseEnumType.E_ENCRY_TYPE, Set<String>> entry = it.next();
//            Set<String> keys = entry.getValue();
//
//            Map<String, String> encryResultMap = EncryUtil.encry(keys.stream().toArray(String[]::new), entry.getKey());
//
//            encryResultMap.forEach((k, v) -> {
//                String valueKey = fieldMap.get(k);
//                //TODO 需要对encValue具体进行加密
//                updateWrapper.getParamNameValuePairs().put(valueKey, v);
//            });
//        }
//    }
//}
